<?php

namespace tmcore\services\wechat;

use app\common\enum\ChannelEnum;
use app\common\model\user\User;
use app\common\model\user\UserAuthLog;
use app\common\model\wechat\WechatGroup;
use app\common\model\wechat\WechatUser;
use app\common\service\UserService;
use EasyWeChat\OfficialAccount\Application;
use tmcore\exceptions\WeChatException;
use tmcore\services\upload\Upload;
use tmcore\utils\Helper;

/**
 * 微信公众号用户类
 */
class WxOaUserService
{
    protected WechatUser $wxUserModel;

    protected Application $app;

    protected array $user = [];

    /**
     * 构造函数
     */
    public function __construct()
    {
        $this->wxUserModel = (new WechatUser);
        $this->app = (new WxOaService)->getApplication();
    }

    /**
     * 获取微信用户信息
     * @param array $where
     * @param string $field
     * @return array
     */
    public function getWxUserInfo(array $where, $field = '*')
    {
        return $this->wxUserModel->where($where)->field($field)->findOrEmpty()->toArray();
    }

    /**
     * 根据uid获取openid
     * @param int $uid
     * @return mixed
     */
    public function uidToOpenid(int $uid)
    {
        return $this->wxUserModel->where(['uid' => $uid])->value('openid');
    }


    /**
     * 设置微信关注
     * @param $openid
     * @param bool $is_subscribe
     * @param int $time
     * @return bool
     * @throws WeChatException
     */
    public function setUserSubscribe($openid, $is_subscribe = true, $time = 0)
    {
        if($is_subscribe) {
            if(!$this->wxUserModel->where(['openid' => $openid])->update(['is_subscribe' => 1, 'subscribe_time' => $time?:time()])) {
                throw new WeChatException('微信公众号关注失败');
            }
        } else {
            if(!$this->wxUserModel->where(['openid' => $openid])->update(['is_subscribe' => 0, 'unfollow_time' => $time?:time()])) {
                throw new WeChatException('微信公众号取关失败');
            }
        }
        return true;
    }

    /**
     * 用户授权登录
     * @param $params
     * @return array
     * @throws WeChatException
     */
    public function authUserLogin($params)
    {
        if(empty($params['openid'])) throw new WeChatException('openid不可为空');
        if ($this->checkUserAuth($params)) {
            return $this->updateUser($params);
        } else {
            return $this->addUser($params);
        }
    }

    /**
     * 检查用户授权
     * @param $params
     * @return array|bool
     * @throws WeChatException
     */
    public function checkUserAuth($params) {

        // 授权记录检验
        $auth = UserAuthLog::where(['openid' => $params['openid']])->field('id,uid,openid,unionid')->findOrEmpty()->toArray();

        if(!$auth && (!empty($params['unionid']))) {
            $auth = UserAuthLog::where(['unionid' => $params['unionid']])->field('id,uid,openid,unionid')->findOrEmpty()->toArray();
        }

        // 手机号唯一用户检验
        if(!empty($params['mobile'])) {
            $auth['uid'] = User::where(['mobile' => $params['mobile']])->value('id');
        }

         if(!$auth) return false;

         $user = User::where(['id' => $auth['uid']])->field('id,avatar,nickname,user_token,mobile,status')->findOrEmpty()->toArray();
         if($user['status'] == 0) throw new WeChatException('您的账号已被禁用，请联系客服');
         $this->user = $user;

         return $user;
    }

    /**
     * 更新微信粉丝信息
     * @param $params
     * @return array
     * @throws WeChatException
     */
    public function updateUser($params)
    {
        $info = $this->getWxUserInfo(['openid' => $params['openid']]);

        if($info) {
            $update = [];

            // 昵称
            if(isset($params['nickname']) && $params['nickname'] && $info['nickname'] != Helper::filter_emoji($params['nickname'])) {
                $update['nickname'] = Helper::filter_emoji($params['nickname']);
            }

            // 头像
            $default_avatar = config('core.default_image')['user_avatar'];
            if(isset($params['headimgurl']) && $params['headimgurl'] && $info['avatar'] == $default_avatar) {
                $update['avatar'] = $this->downloadUserAvatar($params['headimgurl']);
            }

            // unionid
            if(isset($params['unionid']) && $params['unionid'] && empty($info['unionid'])) {
                $update['unionid'] = $params['unionid'];
            }

            // 性别
            if(isset($params['sex']) && $info['sex'] != $params['sex']) {
                $update['sex'] = $params['sex'];
            }

            // 省份
            if(isset($params['province']) && $info['province'] != $params['province']) {
                $update['province'] = $params['province'];
            }

            // 城市
            if(isset($params['city']) && $info['city'] != $params['city']) {
                $update['city'] = $params['city'];
            }

            // 国家
            if(isset($params['country']) && $info['country'] != $params['country']) {
                $update['country'] = $params['country'];
            }

            // 检测修改更新信息
            if($update && (!$this->wxUserModel->where(['openid' => $params['openid']])->edit($update, $params['openid'], 'openid'))) {
                throw new  WeChatException('更新微信信息失败');
            }
        } else  {
            $this->addWxUser($params);
        }

        // 检验用户授权记录
        (new UserService)->userAuth($this->user['id'], ChannelEnum::WX_OA, $params['openid'], $params['unionid']??'');

        //更新登录信息
        User::where(['id' => $this->user['id']])->update(['last_time' => time(), 'last_ip' => request()->ip()]);

        return [
            'uid' => $this->user['id'],
            'openid' => $params['openid'],
            'unionid' => $info['unionid'] ?? $params['unionid']
        ];
    }

    /**
     * 新增用户
     * @param $params
     * @return array
     * @throws WeChatException
     */
    public function addUser($params) {

        try {

            $this->user['nickname'] = empty($params['nickname']) ? ('wx_' . com_random(10,'0123456789')) : Helper::filter_emoji($params['nickname']);
            $this->user['avatar'] = empty($params['headimgurl']) ? (config('core.default_image')['user_avatar']) : $this->downloadUserAvatar($params['headimgurl']);

            $userService = (new UserService);

            // 新用户注册
            $res = $userService->register([
                'account' => 'wx_oa_' . com_random(10,'0123456789'),
                'password' => '123456',
                'channel' => ChannelEnum::WX_OA,
                'avatar' => $this->user['avatar'],
                'nickname' => $this->user['nickname'],
                'openid' => $params['openid']
            ]);

            if(empty($res['id'])) throw new WeChatException('新增用户失败');

            $this->user['id'] = $res['id'];

            $this->addWxUser($params);

            // 检验用户授权记录
            $userService->userAuth($this->user['id'], ChannelEnum::WX_OA, $params['openid'], $params['unionid'] ?? '');

            return [
                'uid' => $this->user['id'],
                'openid' => $params['openid'],
                'unionid' => $params['unionid'] ?? '',
            ];

        } catch (\Exception $e) {
            throw new WeChatException($e->getMessage());
        }
    }

    /**
     * 新增微信用户
     * @param $params
     * @return bool
     * @throws WeChatException
     */
    private function addWxUser($params) {
        // 获取微信用户信息
        $userInfo = (new WxOaService)->getUserInfo($params['openid']);

        if(empty($userInfo['openid'])) throw new WeChatException('获取微信用户信息失败');

        if(isset($this->user['nickname'])) {
            $userInfo['nickname'] = $this->user['nickname'];
        } else {
            if(empty($userInfo['nickname'])) { //昵称
                $userInfo['nickname'] = 'wx_' . com_random(10,'0123456789');
            } else {
                $userInfo['nickname'] = Helper::filter_emoji($userInfo['nickname']);
            }
        }

        if(isset($this->user['avatar'])) {
            $userInfo['avatar'] = $this->user['avatar'];
        } else  {
            if(empty($params['headimgurl'])) { //头像
                $userInfo['avatar'] = config('core.default_image')['user_avatar'];
            } else {
                $userInfo['avatar'] = $this->downloadUserAvatar($params['headimgurl']);
            }
        }

        if (!empty($userInfo['tagid_list'])) { //标签
            $userInfo['tagid_list'] = implode(',', $userInfo['tagid_list']);
        }

        if(empty($userInfo['groupid'])) { //分组
            $userInfo['group_id'] = 0;
        } else {
            $userInfo['group_id'] = WechatGroup::where(['group_id' => $userInfo['groupid']])->value('id');
        }

        $data = [
            'uid' => $this->user['id'],
            'unionid' => $userInfo['unionid'] ?? '',
            'openid' => $userInfo['openid'],
            'nickname' => $userInfo['nickname'],
            'avatar' => $userInfo['avatar'],
            'sex' => $params['sex'] ?? 0,
            'city' => $params['city'] ?? '',
            'province' => $params['province'] ?? '',
            'country' => $params['country'] ?? '',
            'group_id' => $userInfo['group_id'],
            'tagid_list' => $userInfo['tagid_list'],
            'remark' => $userInfo['remark'] ?? '',
            'is_subscribe' => $userInfo['subscribe'] ?? 0,
            'subscribe_time' => $userInfo['subscribe_time'] ?? 0
        ];

        // 新增微信粉丝
        $res =  $this->wxUserModel->add($data);
        if(!$res) throw new WeChatException('新增微信用户失败');
        return true;
    }

    /**
     * 下载头像图片
     * @param $url
     * @return mixed
     * @throws WeChatException
     */
    private function downloadUserAvatar($url)
    {
        // 下载图片到本地
        $uploadService = (new Upload);
        try {
            $result = $uploadService->fetch($url);
            return $result['url'];
        } catch (\Exception $e) {
            throw new WeChatException($e->getMessage());
        }
    }
}